home *** CD-ROM | disk | FTP | other *** search
/ CD Actual 1 / PC Actual CD 01.iso / f1 / cimb.arj / PCX.C < prev    next >
Encoding:
C/C++ Source or Header  |  1994-09-01  |  11.2 KB  |  528 lines

  1. /*==============================================================================
  2.  
  3. FICHERO: PCX.C
  4.  
  5. AUTOR: ANTONIO LADESA JURADO
  6.  
  7. FECHA: 24/6/94
  8.  
  9. DESCRIPCION:
  10.  
  11.     Fichero que contiene las estructuras, constantes, variables y funciones
  12.     internas y externas para el procesamiento de ficheros PCX.
  13.  
  14. ==============================================================================*/
  15.  
  16.  
  17. /*---- MODULOS USADOS --------------------------------------------------------*/
  18.  
  19. #include <stdio.h>
  20. #include <alloc.h>
  21. #include <string.h>
  22.  
  23. #include "global.h"
  24. #include "memoria.h"
  25. #include "video.h"
  26. #include "pcx.h"
  27. #include "error.h"
  28.  
  29.  
  30. /*---- ESTRUCTURAS, CONSTANTES Y VARIABLES LOCALES AL MODULO -----------------*/
  31.  
  32.  
  33.     /* cabecera de un fichero pcx */
  34. typedef struct
  35.     {
  36.     char fabricante;
  37.     char version;
  38.     char codificacion;
  39.     char bits_por_pixel;
  40.     int xmin,ymin;
  41.     int xmax,ymax;
  42.     int ppp_hor;
  43.     int ppp_ver;
  44.     char paleta[48];
  45.     char reservado;
  46.     char planos_color;
  47.     int bytes_por_linea;
  48.     int tipo_paleta;
  49.     char relleno[58];
  50.     }
  51. CABpcx;
  52.  
  53.     /* cabecera del fichero PCX */
  54. static CABpcx cabecera;
  55.     /* contadores auxiliares */
  56. static int iant=0,cant=0;
  57.  
  58.  
  59. /*---- DEFINICION DE LAS FUNCIONES INTERNAS ----------------------------------*/
  60.  
  61.  
  62. IMAGEN *PCXleerCabecera(IMAGEN *c,FILE *f,char *nombre);
  63. IMAGEN *PCXleerImagen(IMAGEN *c,FILE *);
  64. void PCXleerLinea(char *, FILE *,int);
  65.  
  66. void PCXescribirImagen(IMAGEN *c,FILE *f);
  67. void PCXescribirLinea(char *p, FILE *f, int bytes);
  68. void PCXcrearCabecera(IMAGEN *c);
  69.  
  70.  
  71. /*---- CODIFICACION DE LAS FUNCIONES OFRECIDAS -------------------------------*/
  72.  
  73.  
  74. /*---- FUNCION: extern IMAGEN *PCXcargar(char *nombre,IMAGEN *c) ---------------
  75.  
  76.     Descripción:
  77.  
  78.         Esta función carga en memoria una imagen de tipo PCX.
  79.  
  80.     Parámetros:
  81.  
  82.         char *nombre : nombre del fichero a cargar
  83.         IMAGEN *c : puntero a estructura que alberga la imagen
  84.  
  85.     Retorno:
  86.  
  87.         Puntero a la estructura de la imagen o NULL si hubo error
  88.  
  89. ---- CODIGO: -----------------------------------------------------------------*/
  90.  
  91. extern IMAGEN *PCXcargar(char *nombre,IMAGEN *c)
  92. {
  93. FILE *f;
  94.  
  95.     /* abrir el fichero */
  96. if((f = fopen(nombre, "rb")) != NULL)
  97.     {
  98.         /* leer cabecera PCX */
  99.     if((c = PCXleerCabecera(c,f,nombre))!=NULL)
  100.             /* leer imagen */
  101.         c = PCXleerImagen(c,f);
  102.     fclose(f);
  103.     }
  104. else
  105.     {
  106.     ERRORponer(ERRapertura);
  107.     return(NULL);
  108.     }
  109. return(c);
  110. }
  111.  
  112. /*---- FIN FUNCION -----------------------------------------------------------*/
  113.  
  114.  
  115. /*---- FUNCION: extern int *PCXsalvar(char *nombre,IMAGEN *c) ------------------
  116.  
  117.     Descripción:
  118.  
  119.         Esta función salva en disco una imagen con formato PCX.
  120.  
  121.     Parámetros:
  122.  
  123.         char *nombre : nombre del fichero a salvar
  124.         IMAGEN *c : puntero a estructura que alberga la imagen
  125.  
  126.     Retorno:
  127.  
  128.         - 0 si hay error
  129.         - 1 en caso contrario
  130.  
  131. ---- CODIGO: -----------------------------------------------------------------*/
  132.  
  133. extern int PCXsalvar(char *fichero,IMAGEN *c)
  134. {
  135.     /* puntero al fichero de salida */
  136. FILE *f;
  137.  
  138.     /* abrir el fichero */
  139. if((f = fopen(fichero, "wb")) == NULL)
  140.     {
  141.     ERRORponer(ERRapertura);
  142.     return(0);
  143.     }
  144.     /* adecuar el modo de video a la imagen */
  145. if(c->modo == VIDEOvga && c->colores <= 16)
  146.     c=VIDEOvision(c);
  147.  
  148.     /* crear la cabecera PCX */
  149. PCXcrearCabecera(c);
  150.     /* escribir la cabecera PCX */
  151. if(fwrite((char *)&cabecera,1,sizeof(CABpcx),f) != sizeof(CABpcx))
  152.     {
  153.     ERRORponer(ERRescritura);
  154.     fclose(f);
  155.     return(0);
  156.     }
  157.     /* escribir la imagen PCX */
  158. PCXescribirImagen(c,f);
  159.  
  160.     /* si tiene más de 16 colores, escribir paleta PCX */
  161. if(c->modo == VIDEOvga)
  162.     {
  163.     fputc(0xC,f);
  164.     fwrite(c->paleta,768,1,f);
  165.     }
  166. fclose(f);
  167. return(1);
  168. }
  169.  
  170. /*---- FIN FUNCION -----------------------------------------------------------*/
  171.  
  172.  
  173. /*---- CODIFICACION DE LAS FUNCIONES INTERNAS --------------------------------*/
  174.  
  175.  
  176. /*---- FUNCION: IMAGEN *PCXleerCabecera(IMAGEN *c,FILE *f,char *nombre) --------
  177.  
  178.     Descripción:
  179.  
  180.         Esta función reserva memoria para la imagen y lee la cabecera del fichero
  181.         PCX.
  182.  
  183.     Parámetros:
  184.  
  185.  
  186.         IMAGEN *c : puntero a estructura que alberga la imagen
  187.         FILE *f : puntero al fichero
  188.         char *nombre : nombre del fichero a cargar
  189.  
  190.     Retorno:
  191.  
  192.         Puntero a la estructura de la imagen o NULL si hubo error
  193.  
  194. ---- CODIGO: -----------------------------------------------------------------*/
  195.  
  196. IMAGEN *PCXleerCabecera(IMAGEN *c,FILE *f,char *nombre)
  197. {
  198.     /* leer cabecera PCX */
  199. if(fread((char *)&cabecera,1,sizeof(CABpcx),f) == sizeof(CABpcx))
  200.     {
  201.         /* comprobar que es un PCX */
  202.     if(cabecera.fabricante != 0x0a)
  203.         {
  204.         ERRORponer(ERRnoTratado);
  205.         return(NULL);
  206.         }
  207.     }
  208. else
  209.     {
  210.     ERRORponer(ERRlectura);
  211.     return(NULL);
  212.     }
  213.  
  214.      /* reservar memoria para la cabecera de trabajo */
  215. if((c=MEMreservarCAB(c))==NULL)
  216.     {
  217.     ERRORponer(ERRnoMemoria);
  218.     return(NULL);
  219.     }
  220.  
  221.     /* cargar cabecera de trabajo */
  222. strcpy(c->nombre,nombre);
  223. c->ancho = cabecera.xmax - cabecera.xmin + 1;
  224. c->alto = cabecera.ymax - cabecera.ymin + 1;
  225. c->bytes = cabecera.bytes_por_linea;
  226. c->formato = PCX;
  227.  
  228.     /* determinar tipo de imagen */
  229. switch(cabecera.bits_por_pixel)
  230.     {
  231.     case 1:
  232.         {
  233.             /* monocromática */
  234.         if(cabecera.planos_color == 1)
  235.             {
  236.             c->modo = VIDEOmono;
  237.             c->colores = 2;
  238.             c->haypaleta = FALSO;
  239.             }
  240.         else
  241.                 /* 16 colores */
  242.             if(cabecera.planos_color == 4)
  243.                 {
  244.                 c->modo = VIDEOega;
  245.                 c->colores = 16;
  246.                 c->bytes*=4;
  247.                 c->haypaleta = CIERTO;
  248.                 memcpy(c->paleta,&cabecera.paleta,48);
  249.                 }
  250.             else
  251.                 {
  252.                     /* formato desconocido */
  253.                 ERRORponer(ERRnoTratado);
  254.                 return(NULL);
  255.                 }
  256.         };
  257.     break;
  258.  
  259.     case 8:
  260.         if(cabecera.planos_color != 1)
  261.             {
  262.                 /* formato desconocido */
  263.             ERRORponer(ERRnoTratado);
  264.             return(NULL);
  265.             }
  266.             /* 256 colores */
  267.         c->modo = VIDEOvga;
  268.         c->colores = 256;
  269.         c->haypaleta = CIERTO;
  270.             /* leer paleta 256 colores */
  271.         fseek(f,-768L,SEEK_END);
  272.         if(fread((char *)c->paleta,1,768,f) != 768)
  273.             {
  274.             ERRORponer(ERRlectura);
  275.             return(NULL);
  276.             }
  277.     break;
  278.  
  279.     default:
  280.             /* formato desconocido */
  281.         ERRORponer(ERRnoTratado);
  282.     return(NULL);
  283.     }
  284.  
  285.     /* si no hay memoria para la imagen, liberar cabecera */
  286. if(!MEMreservar(c))
  287.     {
  288.     c =MEMliberar(c);
  289.     ERRORponer(ERRnoMemoria);
  290.     return(c);
  291.     }
  292. return(c);
  293. }
  294.  
  295. /*---- FIN FUNCION -----------------------------------------------------------*/
  296.  
  297.  
  298. /*---- FUNCION: IMAGEN *PCXleerImagen(IMAGEN *c,FILE *f) -----------------------
  299.  
  300.     Descripción:
  301.  
  302.         Esta función carga en memoria una imagen de tipo PCX.
  303.  
  304.     Parámetros:
  305.  
  306.  
  307.         IMAGEN *c : puntero a estructura que alberga la imagen
  308.         FILE *f : puntero al fichero
  309.  
  310.     Retorno:
  311.  
  312.         Puntero a la estructura de la imagen
  313.  
  314. ---- CODIGO: -----------------------------------------------------------------*/
  315.  
  316. IMAGEN *PCXleerImagen(IMAGEN *c,FILE *f)
  317. {
  318.     /* contador de líneas */
  319. int i;
  320.     /* buffer */
  321. char p[ANCHO_MAXIMO];
  322.  
  323.     /* inicializar variables estáticas para la lectura de líneas */
  324. iant=cant=0;
  325.     /* posicionar puntero al inicio de la imagen */
  326. fseek(f,128L,SEEK_SET);
  327.     /* cargar imagen */
  328. for(i = 0; i < c->alto ; i++)
  329.     {
  330.     PCXleerLinea(p,f,c->bytes);
  331.     MEMescribir(p,i,c);
  332.     }
  333. return(c);
  334. }
  335.  
  336. /*---- FIN FUNCION -----------------------------------------------------------*/
  337.  
  338.  
  339. /*---- FUNCION: void PCXleerLinea(char *p, FILE *f,int bytes) ------------------
  340.  
  341.     Descripción:
  342.  
  343.         Esta función lee una línea de un fichero PCX.
  344.  
  345.     Parámetros:
  346.  
  347.         char *p : puntero a buffer donde se almacena la línea
  348.         FILE *f : puntero al fichero
  349.         int bytes: numero de bytes por linea
  350.  
  351. ---- CODIGO: -----------------------------------------------------------------*/
  352.  
  353. void PCXleerLinea(char *p, FILE *f,int bytes)
  354. {
  355.     /* contadores */
  356. int n = 0,i,cont;
  357.  
  358. memset(p,0,bytes);
  359.     /* descomprimir línea */
  360. do
  361.     {
  362.         /* si hay bytes de esta línea leidos antes, llevarlos al buffer */
  363.     if(iant)
  364.         {
  365.         i = iant;
  366.         cont = cant;
  367.         iant = cant = 0;
  368.         while(i--)
  369.                 p[n++]=cont;
  370.         }
  371.     else
  372.         {
  373.         cont = fgetc(f) & 0xff;
  374.             /* si hay un contador, guardarlo en 'i' */
  375.         if( (cont & 0xC0) == 0xC0)
  376.             {
  377.             i = cont & 0x3F;
  378.                 /* leer dato */
  379.             cont = fgetc(f) & 0xff;
  380.                 /* si sobrepasa el ancho, guardarlos para la siguiente línea */
  381.             if(i+n > bytes)
  382.                 {
  383.                 cant = cont;
  384.                 iant = (i+n-bytes);
  385.                 i=bytes-n;
  386.                 }
  387.                 /* repetir el dato 'i' veces */
  388.             while(i--)
  389.                 p[n++]=cont;
  390.             }
  391.         else
  392.                 /* si no hay contador, es un dato */
  393.             p[n++]=cont;
  394.         }
  395.     }
  396. while(n < bytes);
  397. }
  398.  
  399. /*---- FIN FUNCION -----------------------------------------------------------*/
  400.  
  401.  
  402. /*---- FUNCION: void PCXcrearCabecera(IMAGEN *c) -------------------------------
  403.  
  404.     Descripción:
  405.  
  406.         Esta función crea una cabecera PCX.
  407.  
  408.     Parámetros:
  409.  
  410.         IMAGEN *c : puntero a estructura que alberga la imagen
  411.  
  412. ---- CODIGO: -----------------------------------------------------------------*/
  413.  
  414. void PCXcrearCabecera(IMAGEN *c)
  415. {
  416.     /* rellenar los datos de la cabecera */
  417. cabecera.fabricante = 0x0A;
  418. cabecera.version = 5;
  419. cabecera.codificacion = 1;
  420. cabecera.xmin = cabecera.ymin = 0;
  421. cabecera.xmax = c->ancho - 1;
  422. cabecera.ymax = c->alto - 1;
  423. cabecera.ppp_hor = c->ancho;
  424. cabecera.ppp_ver = c->alto;
  425. cabecera.reservado=0;
  426. cabecera.tipo_paleta = 2;
  427. switch(c->modo)
  428.     {
  429.     case VIDEOmono:
  430.         cabecera.bits_por_pixel = 1;
  431.         cabecera.planos_color = 1;
  432.         cabecera.bytes_por_linea = c->bytes;
  433.     break;
  434.     case VIDEOega:
  435.         cabecera.bits_por_pixel = 1;
  436.         cabecera.planos_color = 4;
  437.         cabecera.bytes_por_linea = c->bytes/4;
  438.         memcpy(cabecera.paleta,c->paleta,48);
  439.     break;
  440.     case VIDEOvga:
  441.         cabecera.bits_por_pixel = 8;
  442.         cabecera.planos_color = 1;
  443.         cabecera.bytes_por_linea = c->bytes;
  444.     break;
  445.     }
  446. }
  447.  
  448. /*---- FIN FUNCION -----------------------------------------------------------*/
  449.  
  450.  
  451. /*---- FUNCION: void PCXescribirImagen(IMAGEN *c,FILE *f) ----------------------
  452.  
  453.     Descripción:
  454.  
  455.         Esta función graba la imagen en un fichero PCX.
  456.  
  457.     Parámetros:
  458.  
  459.         IMAGEN *c : puntero a estructura que alberga la imagen
  460.         FILE *f : puntero al fichero
  461.  
  462. ---- CODIGO: -----------------------------------------------------------------*/
  463.  
  464. void PCXescribirImagen(IMAGEN *c,FILE *f)
  465. {
  466.     /* contador de líneas */
  467. int i;
  468.     /* buffer */
  469. char p[ANCHO_MAXIMO];
  470.  
  471.     /* salvar imagen */
  472. for(i = 0; i < c->alto;++i)
  473.     {
  474.     MEMleer(p,i,c);
  475.     PCXescribirLinea(p,f,c->bytes);
  476.     }
  477. }
  478.  
  479. /*---- FIN FUNCION -----------------------------------------------------------*/
  480.  
  481.  
  482. /*---- FUNCION: void PCXescribirLinea(char *p, FILE *f,int bytes) --------------
  483.  
  484.     Descripción:
  485.  
  486.         Esta función escribe una línea en un fichero PCX.
  487.  
  488.     Parámetros:
  489.  
  490.         char *p : puntero a buffer que alberga la línea
  491.         FILE *f : puntero al fichero
  492.         int bytes : numero de bytes por línea
  493.  
  494.     Retorno:
  495.  
  496.         Puntero a la estructura de la imagen o NULL si hubo error
  497.  
  498. ---- CODIGO: -----------------------------------------------------------------*/
  499.  
  500. void PCXescribirLinea(char *p,FILE *f,int bytes)
  501. {
  502.     /* contadores */
  503. unsigned int i=0,t=0;
  504.  
  505. do
  506.     {
  507.     i=0;
  508.     while((p[t+i]==p[t+i+1]) && ((t+i) < bytes) && (i<63))
  509.         ++i;
  510.         /* si es posible, grabar contador y dato */
  511.     if(i>0)
  512.         {
  513.         fputc(i|0xC0,f);
  514.         fputc(p[t],f);
  515.         t+=i;
  516.         }
  517.     else
  518.         {
  519.             /* si el dato ex 0xC0, grabar un contador de 1, y el dato */
  520.         if(((p[t]) & 0xC0) == 0xC0)
  521.             fputc(0xC1,f);
  522.             /* grabar dato */
  523.         fputc(p[t++],f);
  524.         }
  525.     }while(t<bytes);
  526. }
  527.  
  528. /*---- FIN FUNCION -----------------------------------------------------------*/